import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { message } from 'antd';

// 创建axios实例
const createAxiosInstance = (): AxiosInstance => {
  const instance = axios.create({
    baseURL: process.env.REACT_APP_API_BASE_URL || 'http://localhost:8081/api/v1',
    timeout: 10000,
    headers: {
      'Content-Type': 'application/json',
    },
  });

  // 请求拦截器
  instance.interceptors.request.use(
    (config: any) => {
      // 添加认证token
      const token = localStorage.getItem('auth_token');
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }

      // 添加时间戳防止缓存
      if (config.method === 'get') {
        config.params = {
          ...config.params,
          _t: Date.now(),
        };
      }

      return config;
    },
    (error) => {
      console.error('Request error:', error);
      return Promise.reject(error);
    }
  );

  // 响应拦截器
  instance.interceptors.response.use(
    (response: AxiosResponse) => {
      return response;
    },
    (error) => {
      console.error('Response error:', error);

      // 统一错误处理
      if (error.response) {
        const { status, data } = error.response;

        switch (status) {
          case 401:
            // 未授权，清除token并跳转到登录页
            localStorage.removeItem('auth_token');
            localStorage.removeItem('user_info');
            window.location.href = '/login';
            message.error('认证已过期，请重新登录');
            break;

          case 403:
            message.error('权限不足，无法访问该资源');
            break;

          case 404:
            message.error('请求的资源不存在');
            break;

          case 422:
            message.error(data?.message || '请求参数错误');
            break;

          case 500:
            message.error('服务器内部错误，请稍后重试');
            break;

          default:
            message.error(data?.message || `请求失败 (${status})`);
        }
      } else if (error.request) {
        // 网络错误
        message.error('网络连接错误，请检查网络设置');
      } else {
        // 其他错误
        message.error('请求配置错误');
      }

      return Promise.reject(error);
    }
  );

  return instance;
};

// 导出axios实例
export const apiClient = createAxiosInstance();

// HTTP方法封装
export class HttpClient {
  private static instance: HttpClient;
  private client: AxiosInstance;

  private constructor() {
    this.client = createAxiosInstance();
  }

  public static getInstance(): HttpClient {
    if (!HttpClient.instance) {
      HttpClient.instance = new HttpClient();
    }
    return HttpClient.instance;
  }

  // GET请求
  public async get<T = any>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<T> {
    const response = await this.client.get<T>(url, config);
    return response.data;
  }

  // POST请求
  public async post<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ): Promise<T> {
    const response = await this.client.post<T>(url, data, config);
    return response.data;
  }

  // PUT请求
  public async put<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ): Promise<T> {
    const response = await this.client.put<T>(url, data, config);
    return response.data;
  }

  // DELETE请求
  public async delete<T = any>(
    url: string,
    config?: AxiosRequestConfig
  ): Promise<T> {
    const response = await this.client.delete<T>(url, config);
    return response.data;
  }

  // PATCH请求
  public async patch<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ): Promise<T> {
    const response = await this.client.patch<T>(url, data, config);
    return response.data;
  }
}

// 导出HTTP客户端实例
export const httpClient = HttpClient.getInstance();

// 请求重试装饰器
export const withRetry = <T extends (...args: any[]) => Promise<any>>(
  fn: T,
  maxRetries: number = 3,
  delay: number = 1000
): T => {
  return (async (...args: Parameters<T>): Promise<ReturnType<T>> => {
    let lastError: any;

    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        return await fn(...args);
      } catch (error) {
        lastError = error;
        
        if (attempt === maxRetries) {
          throw error;
        }

        // 指数退避延迟
        const retryDelay = delay * Math.pow(2, attempt - 1);
        await new Promise(resolve => setTimeout(resolve, retryDelay));
        
        console.warn(`Request failed (attempt ${attempt}/${maxRetries}), retrying in ${retryDelay}ms...`, error);
      }
    }

    throw lastError;
  }) as T;
};

// 请求取消token管理
export class RequestCancelManager {
  private static pendingRequests = new Map<string, AbortController>();

  public static createCancelToken(key: string): AbortSignal {
    // 取消之前的请求
    this.cancelRequest(key);

    // 创建新的取消token
    const controller = new AbortController();
    this.pendingRequests.set(key, controller);
    return controller.signal;
  }

  public static cancelRequest(key: string): void {
    const controller = this.pendingRequests.get(key);
    if (controller) {
      controller.abort();
      this.pendingRequests.delete(key);
    }
  }

  public static cancelAllRequests(): void {
    this.pendingRequests.forEach((controller) => {
      controller.abort();
    });
    this.pendingRequests.clear();
  }
}

export default httpClient;
